﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace CourseManagerment.Controls
{
    /// <summary>
    /// Instrument.xaml 的交互逻辑
    /// </summary>
    public partial class Instrument : UserControl
    {

        // Using a DependencyProperty as the backing store for Interval.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IntervalProperty =
            DependencyProperty.Register("Interval", typeof(int), typeof(Instrument),
                new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));

        // Using a DependencyProperty as the backing store for Maximum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(int), typeof(Instrument),
                new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));

        // Using a DependencyProperty as the backing store for Minimum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(int), typeof(Instrument),
                new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));

        // Using a DependencyProperty as the backing store for PlateBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlateBackgroundProperty =
            DependencyProperty.Register("PlateBackground", typeof(Brush), typeof(Instrument), new PropertyMetadata(default(Brush)));

        // Using a DependencyProperty as the backing store for ScaleBrush.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ScaleBrushProperty =
            DependencyProperty.Register("ScaleBrush", typeof(Brush), typeof(Instrument),
                new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPorpertyChanged)));

        // Using a DependencyProperty as the backing store for ScaleTextSize.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ScaleTextSizeProperty =
            DependencyProperty.Register("ScaleTextSize", typeof(int), typeof(Instrument),
                new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));

        public static readonly DependencyProperty ValueProperty =
                    DependencyProperty.Register("Value", typeof(int), typeof(Instrument),
                        new PropertyMetadata(default(int), new PropertyChangedCallback(OnPorpertyChanged)));

        public Instrument()
        {
            InitializeComponent();
            this.SizeChanged += Instrument_SizeChanged;
        }

        /// <summary>
        /// 刻度区间
        /// </summary>
        public int Interval
        {
            get { return (int)GetValue(IntervalProperty); }
            set { SetValue(IntervalProperty, value); }
        }

        /// <summary>
        /// 最大刻度
        /// </summary>
        public int Maximum
        {
            get { return (int)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        /// <summary>
        /// 最小刻度
        /// </summary>
        public int Minimum
        {
            get { return (int)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        /// <summary>
        /// 底盘颜色
        /// </summary>
        public Brush PlateBackground
        {
            get { return (Brush)GetValue(PlateBackgroundProperty); }
            set { SetValue(PlateBackgroundProperty, value); }
        }
        /// <summary>
        /// 刻度数字的颜色
        /// </summary>
        public Brush ScaleBrush
        {
            get { return (Brush)GetValue(ScaleBrushProperty); }
            set { SetValue(ScaleBrushProperty, value); }
        }

        /// <summary>
        /// 字体大小
        /// </summary>
        public int ScaleTextSize
        {
            get { return (int)GetValue(ScaleTextSizeProperty); }
            set { SetValue(ScaleTextSizeProperty, value); }
        }

        /// <summary>
        /// 依赖属性,依赖对象，值
        /// </summary>
        public int Value
        {
            get { return (int)this.GetValue(ValueProperty); }
            set { this.SetValue(ValueProperty, value); }
        }
        public static void OnPorpertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            (o as Instrument).Refresh();
        }
        private void Instrument_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            double minSize = Math.Min(this.RenderSize.Width, this.RenderSize.Height);
            this.backEllipse.Width = minSize;
            this.backEllipse.Height = minSize;
        }

        //更新画图
        private void Refresh()
        {
            double radius = this.backEllipse.Width / 2;//中心坐标
            if (double.IsNaN(radius)) return;
            this.mainCanvas.Children.Clear();

            //double min = 0, max = 100;
            //double scaleAreaCount = 10;//区间
            double step = 270.0 / (this.Maximum - this.Minimum);

            for (int i = 0; i < this.Maximum - this.Minimum; i++)
            {
                Line linScale = new();
                linScale.X1 = radius - (radius - 13) * Math.Cos((i * step - 45) * Math.PI / 180);
                linScale.Y1 = radius - (radius - 13) * Math.Sin((i * step - 45) * Math.PI / 180);
                linScale.X2 = radius - (radius - 8) * Math.Cos((i * step - 45) * Math.PI / 180);
                linScale.Y2 = radius - (radius - 8) * Math.Sin((i * step - 45) * Math.PI / 180);
                linScale.Stroke = this.ScaleBrush;
                linScale.StrokeThickness = 1;

                this.mainCanvas.Children.Add(linScale);

            }

            step = 270.0 / this.Interval;//大刻度
            int scaleText = this.Minimum;
            for (int i = 0; i <= this.Interval; i++)
            {
                Line linScale = new();
                linScale.X1 = radius - (radius - 20) * Math.Cos((i * step - 45) * Math.PI / 180);
                linScale.Y1 = radius - (radius - 20) * Math.Sin((i * step - 45) * Math.PI / 180);
                linScale.X2 = radius - (radius - 8) * Math.Cos((i * step - 45) * Math.PI / 180);
                linScale.Y2 = radius - (radius - 8) * Math.Sin((i * step - 45) * Math.PI / 180);
                linScale.Stroke = this.ScaleBrush;
                linScale.StrokeThickness = 1;

                this.mainCanvas.Children.Add(linScale);

                TextBlock textScale = new()
                {
                    Width = 34,
                    TextAlignment = TextAlignment.Center,
                    FontSize = this.ScaleTextSize,
                    Text = (scaleText + (this.Maximum - this.Minimum) / this.Interval * i).ToString(),
                    Foreground = this.ScaleBrush
                };
                Canvas.SetLeft(textScale, radius - (radius - 36) * Math.Cos((i * step - 45) * Math.PI / 180) - 17);
                Canvas.SetTop(textScale, radius - (radius - 36) * Math.Sin((i * step - 45) * Math.PI / 180) - 10);
                this.mainCanvas.Children.Add(textScale);
            }

            //string sData = "M100 200 A100 100 0 1 1 200 300";
            string sData = "M{0} {1} A{0} {0} 0 1 1 {1} {2}";
            sData = string.Format(sData, radius / 2, radius, radius * 1.5);
            var converter = TypeDescriptor.GetConverter(typeof(Geometry));//集合图形转换器
            this.circle.Data = (Geometry)converter.ConvertFrom(sData);


            step = 270.0 / (this.Maximum - this.Minimum);//大刻度
            //this.rtPoint.Angle= this.Value * step - 45;
            //动画
            DoubleAnimation doubleAnimation = new((this.Value - this.Minimum) * step - 45, new Duration(TimeSpan.FromMilliseconds(200)));
            this.rtPoint.BeginAnimation(RotateTransform.AngleProperty, doubleAnimation);

            sData = "M{0} {1},{1} {2},{1} {3}";
            sData = string.Format(sData, radius * 0.3, radius, radius - 5, radius + 5);
            this.pointer.Data = (Geometry)converter.ConvertFrom(sData);
        }
    }
}
